Angular Custom Validator

In this tutorial, we shall see how to create a custom validator and assign it to a FormControl.

Angular provides us with few in-built validators which can be used for validation. But there may be some scenarios in which we need to give custom validation to our control. In such a case, we create a custom validator.

Create an angular application

Let's start with an example program. First, create an angular application using

ng new angular-app

Then enter into the project using

cd angular-app

Add ReactiveFormsModule to the project

To use reactive forms, we need to import ReactiveFormsModule in our app.module.ts file.

Let's modify the code in our app.module.ts to import the ReactiveFormsModule and add it to imports array.

  import { BrowserModule } from '@angular/platform-browser';
  import { ReactiveFormsModule } from '@angular/forms';
  import { NgModule } from '@angular/core';
  import { AppRoutingModule } from './app-routing-module';
  import { AppComponent } from './app.component';
  
  @NgModule({
    declarations: [
      AppComponent
    ],
    imports: [
      AppRoutingModule,
      ReactiveFormsModule,
    ],
    providers: [],
    bootstrap: [AppComponent]
  })
  export class AppModule { }

Next, create a new component named, AddEmployeeComponent using the following command.

ng g c add-employee

Let's modify the app-employee.component.ts file

  import { Component, OnInit } from '@angular/core';
  import { FormBuilder, FormGroup, Validators } from '@angular/forms';
  
  @Component({
    selector: 'app-add-employee',
    templateUrl: './add-employee.component.html',
    styleUrls: ['./add-employee.component.css']
  })
  export class AddEmployeeComponent implements OnInit {
  
    employeeForm: FormGroup;
    gender = [
      { key: 'male', value: 'Male' },
      { key: 'female', value: 'Female' }
    ];
  
    constructor(private fb: FormBuilder) { }
  
    ngOnInit() {
      this.employeeForm = this.fb.group({
        name: ['', Validators.required],
        age: ['', [Validators.required ]],
        gender: ['', Validators.required]
      });
    }
  
    onSubmit() {
      console.log(this.employeeForm);
    }
  }

In ngOnInit() life cycle event, we create a FormGroup named employeeForm and assign a FormGroup by creating formGroup with the fb which is a FormBuilder .

The FormGroup contains 3 FormControl named name, age and gender. The name and gender FormControl's contains default value of empty string and a singlerequired validator.

Similarly, for age FormControl, we assign a default value of empty string and to this control we are going to apply multiple validation to this control, so we use array([]) notation for it. So the code looks something like below.

    ngOnInit() {
      this.employeeForm = this.fb.group({
        name: ['', Validators.required],
        age: ['', [Validators.required ]],
        gender: ['', Validators.required]
      });
    }

Let's create a custom validator and assign it to the age FormControl.

Create Custom Validator

Create a folder named custom-validator and create a file named age-validator.ts and modify the code as below.

  import { FormControl } from '@angular/forms';
  
  export function ageValidator(formControl: FormControl): { [key: string]: boolean } | null {
      const age = formControl.value;
      console.log(age);
      if (age > 80) {
          return { ageInValid: true };
      }
      return null;
  }

The ageValidator gets a FormControl as input.

First, get the value from the FormControl using the value property and assign it to age variable.

If the age is greater that 80, then set ageInValid property which is the custom validation property to true and return the object.

If the age is less that 80, then return null which represents no validation error.

Adding the Custom Validator to FormControl

Next, add the custom validator to the age FormControl by adding the ageValidator to validator array of AddEmployeeComponent.

  import { Component, OnInit } from '@angular/core';
  import { FormBuilder, FormGroup, Validators } from '@angular/forms';
  import { ageValidator } from '../custom-validator/age.validator';
  @Component({
    selector: 'app-add-employee',
    templateUrl: './add-employee.component.html',
    styleUrls: ['./add-employee.component.css']
  })
  export class AddEmployeeComponent implements OnInit {
  
    employeeForm: FormGroup;
    gender = [
      { key: 'male', value: 'Male' },
      { key: 'female', value: 'Female' }
    ];
  
    constructor(private fb: FormBuilder) { }
  
    ngOnInit() {
      this.employeeForm = this.fb.group({
        name: ['', Validators.required],
        age: ['', [Validators.required, ageValidator]],
        gender: ['', Validators.required]
      });
    }
  
    onSubmit() {
      console.log(this.employeeForm);
    }
  }

Show up the validation message in HTML Template

In add-employee.component.html file, we modify the code as below

<div>
        <form [formGroup]='employeeForm' (ngSubmit)='onSubmit()'>
          <div>
            <label for='name'>Employee Name</label>
            <input type='text' formControlName='name' />
            <span *ngIf="!employeeForm.get('name').valid && employeeForm.get('name').touched">
              Name is required!
            </span>
          </div>
          <div>
            <label for='age'>Employee Age</label>
            <input type='number' formControlName='age' />
            <span
              *ngIf="!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.required">
              Age is required!
            </span>
            <span
              *ngIf="!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.ageInValid">
              Age should not exceed 80!
            </span>
          </div>
          <div>
            <label for='age'>Employee Age</label>
            <select formControlName='gender'>
              <option>--select--</option>
              <option *ngFor='let item of gender' [value]='item.key'>
                {{item.value}}
              </option>
            </select>
          </div>
          <div>
            <input type='submit' value='Submit' [disabled]='!employeeForm.valid' />
          </div>
        </form>
      </div>

In the above example, we have set the validation for name, age and gender FormControls.
To check whether there is validation error for the name FormControl, we get the FormControl from employeeForm as below.

employeeForm.get('age')

Now, we check whether the control's valid property is false and the control has been touched and also check whether their is ageInValid error for the control.

!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.ageInValid

If the age entered is greater than 80, then the custom validator will set ageInValid to true. Now you can apply the selector string app-add-employee to the app.component.ts to make use of it.


Most Read